﻿
namespace n_MDesignPanel
{
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

using n_UserModule;
using n_GUIcoder;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using n_OS;
using n_SG;
using n_SimulateObj;

//*****************************************************
//图形编辑器容器类
public class MDesignPanel : Panel
{
	//Cursor Cursor1;
	//Cursor Cursor2;
	
	public UserModule myModule;
	public UserPortList myPortList;
	public SimulateObj[] mySimObjList;
	public string InitDataList;
	
	bool BackPress;
	
	//摄像机位置
	public float CamMidX;
	public float CamMidY;
	//摄像机放缩比
	public float CamScale;
	
	//当前的鼠标移动位置
	PointF MousePoint;
	
	bool RightMouseDown;
	float lastX;
	float lastY;
	
	int InitW;
	int InitH;
	
	Pen GridPen;
	Pen GridPen10;
	
	//构造函数
	public MDesignPanel( int Width, int Height ) : base()
	{
		this.BorderStyle = BorderStyle.None;
		SetStyle(ControlStyles.UserPaint |
		         ControlStyles.AllPaintingInWmPaint |
		         ControlStyles.OptimizedDoubleBuffer |
		         ControlStyles.ResizeRedraw |
		         ControlStyles.SupportsTransparentBackColor,true);
		
		//Cursor1 = new Cursor( OS.SystemRoot + "Resource" + OS.PATH_S + "myPointEdit.cur" );
		//Cursor2 = new Cursor( OS.SystemRoot + "Resource" + OS.PATH_S + "myPointMove.cur" );
		
		//this.Cursor = Cursor1;
		
		this.Dock = DockStyle.Fill;
		
		this.MouseMove += new MouseEventHandler( UserMouseMove );
		this.MouseUp += new MouseEventHandler( UserMouseUp );
		this.MouseDown += new MouseEventHandler( UserMouseDown );
		this.MouseWheel += new MouseEventHandler( UserMouseWheel );
		
		CreatSimList();
		
		UserPort.Init();
		myPortList = new UserPortList();
		
		BackPress = false;
		
		CamMidX = Width/2;
		CamMidY = Height/2;
		CamScale = 1;
		
		RightMouseDown = false;
		lastX = 0;
		lastY = 0;
		
		InitW = Width;
		InitH = Height;
		
		GridPen = new Pen( Color.FromArgb( 100, 200, 200, 200 ), 1 );
		GridPen10 = new Pen( Color.FromArgb( 130, 200, 160, 130 ), 1 );
		
		UserPortList.PortSelChanged = this.PortSelChanged;
	}
	
	//创建仿真对象列表
	public void CreatSimList()
	{
		mySimObjList = new SimulateObj[ 32 ];
		for( int i = 0; i < mySimObjList.Length; ++i ) {
			mySimObjList[i] = null;
		}
	}
	
	//清空仿真对象列表
	public void ClearSimList()
	{
		InitDataList = null;
		for( int i = 0; i < mySimObjList.Length; ++i ) {
			mySimObjList[i] = null;
		}
	}
	
	//更新仿真对象数据(需要事先手工清除列表)
	public void SetSimListValue( string s )
	{
		for( int i = 0; i < mySimObjList.Length; ++i ) {
			mySimObjList[i] = null;
		}
		if( s == null || s == "" ) {
			return;
		}
		string[] ss = s.Split( '\n' );
		for( int i = 0; i < ss.Length; ++i ) {
			if( ss[i].StartsWith( "D" ) ) {
				InitDataList = ss[i];
			}
			else {
				mySimObjList[i] = new SimulateObj( null, i );
				mySimObjList[i].SetValue( ss[i] );
			}
		}
	}
	
	//重绘事件
	protected override void OnPaint(PaintEventArgs e)
	{
		Graphics g = e.Graphics;
		
		//禁用图像模糊效果
		e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
		e.Graphics.PixelOffsetMode = PixelOffsetMode.Half;
		
		SG.SetObject( g );
		SG.g.Clear( Color.WhiteSmoke );
		
		float RolX = Width/2;
		float RolY = Height/2;
		
		//摄像机按照中心位置进行旋转
		//SG.Rotate( RolX, RolY, CamAngle );
		//摄像机按照中心位置进行放缩
		SG.Scale( RolX, RolY, CamScale );
		//摄像机移动到指定点
		SG.Transfer( -(CamMidX - RolX), -(CamMidY - RolY) );
		
		//绘制组件
		if( myModule != null ) {
			myModule.Draw( g );
			
			//绘制仿真对象
			for( int i = 0; i < mySimObjList.Length; ++i ) {
				if( mySimObjList[i] != null ) {
					mySimObjList[i].Draw( g, myModule.X, myModule.Y );
				}
			}
		}
		//绘制端口列表
		myPortList.Draw( g, false );
		
		//绘制网格
		DrawCrossPoint( g );
		DrawCrossLine( g );
	}
	
	//导出组件, 正常保存返回 null, 出错返回错误描述
	public void Save( string FileName )
	{
		UserModule.deleSetValue = n_ModuleForm.ModuleForm.ValueBox.Run;
		
		string Mes = "//[配置信息开始],\n";
		Mes += myModule.ToText();
		
		//输出数据初始化项
		if( InitDataList != null ) {
			Mes += "//[Init] " + InitDataList + ",\n";
		}
		//输出仿真对象
		for( int i = 0; i < mySimObjList.Length; ++i ) {
			if( mySimObjList[i] != null ) {
				Mes += mySimObjList[i].ToText();
			}
		}
		Mes += myPortList.ToText( myModule.X, myModule.Y, false );

		Mes += "//[配置信息结束],\n";
		
		//保存组件为独立文件格式
		Stream stream = File.Open( FileName, FileMode.Create );
		BinaryFormatter bin = new BinaryFormatter();
		bin.Serialize( stream, Mes );
		bin.Serialize( stream, myModule.GetCurrentImage() );
		stream.Close();
	}
	
	PointF GetWorldPoint( float mouseX, float mouseY )
	{
		mouseX = mouseX - Width/2;
		mouseY = mouseY - Height/2;
		
		mouseX = mouseX/CamScale;
		mouseY = mouseY/CamScale;
		
		//double R = Math.Cos( -CamAngle * Math.PI/180 );
		//double I = Math.Sin( -CamAngle * Math.PI/180 );
		//double x = mouseX*R - mouseY*I;
		//double y = mouseX*I + mouseY*R;
		
		double x = mouseX;
		double y = mouseY;
		
		return new PointF( (float)(CamMidX + x), (float)(CamMidY + y) );
	}
	
	//端口选择改变时
	void PortSelChanged()
	{
		UserPort seport = UserPortList.SelectedPort;
		if( seport == null ) {
			return;
		}
		//更新端口名称
		n_Main.Program.ModuleBox.textBox名称.Text = seport.Name;
		
		//更新端口方向
		if( seport.DirType == E_DirType.UP ) {
			SetSelectedIndex( n_Main.Program.ModuleBox.comboBox导线方向, "UP", null );
		}
		if( seport.DirType == E_DirType.DOWN ) {
			SetSelectedIndex( n_Main.Program.ModuleBox.comboBox导线方向, "DOWN", null );
		}
		if( seport.DirType == E_DirType.LEFT ) {
			SetSelectedIndex( n_Main.Program.ModuleBox.comboBox导线方向, "LEFT", null );
		}
		if( seport.DirType == E_DirType.RIGHT ) {
			SetSelectedIndex( n_Main.Program.ModuleBox.comboBox导线方向, "RIGHT", null );
		}
		if( seport.DirType == E_DirType.NONE ) {
			SetSelectedIndex( n_Main.Program.ModuleBox.comboBox导线方向, "NONE", null );
		}
		//更新端口主从类型
		if( seport.FuncType == PortClientType.CLIENT ) {
			SetSelectedIndex( n_Main.Program.ModuleBox.comboBoxMasOrCli, PortClientType.CLIENT, null );
		}
		else {
			SetSelectedIndex( n_Main.Program.ModuleBox.comboBoxMasOrCli, PortClientType.MASTER, null );
		}
		//更新功能名称
		SetSelectedIndex( n_Main.Program.ModuleBox.comboBox端口功能名称, seport.FuncName, "," );
		
		n_Main.Program.ModuleBox.textBoxPortExt.Text = seport.ExtValue;
	}
	
	void SetSelectedIndex( ComboBox cb, string text, string Pre )
	{
		for( int i = 0; i < cb.Items.Count; ++i ) {
			string st = Pre + cb.Items[i].ToString() + Pre;
			if( st == text ) {
				cb.SelectedIndex = i;
				return;
			}
		}
		text = text.Trim( Pre[0] );
		cb.Text = text;
		MessageBox.Show( "请核对: 列表中不包含目标文本:<" + text + "> " + Pre );
	}
	
	//鼠标滚轮事件
	public void UserMouseWheel( object sender, MouseEventArgs e )
	{
		PointF p = GetWorldPoint( e.X, e.Y );
		
		if( e.Delta > 0 ) {
			if( CamScale < 500 ) {
				CamScale *= 1.5f;
			}
		}
		else {
			if( CamScale > 0.05 ) {
				CamScale /= 1.5f;
			}
		}
		PointF p1 = GetWorldPoint( e.X, e.Y );
		CamMidX += p.X - p1.X;
		CamMidY += p.Y - p1.Y;
		
		this.Invalidate();
	}
	
	//鼠标按下事件
	void UserMouseDown( object sender, MouseEventArgs e )
	{
		this.Focus();
		
		n_Main.Program.ModuleBox.isChanged = true;
		
		if( e.Button == MouseButtons.Left ) {
			//this.Cursor = Cursor2;
			
			UserPortList.temp = null;
			
			//端口列表鼠标事件
			bool ObjectPress = myPortList.UserMouseDown( e, (int)MousePoint.X, (int)MousePoint.Y );
			
			if( UserPortList.temp != null && UserPortList.temp != UserPortList.SelectedPort ) {
				UserPortList.SelectedPort = UserPortList.temp;
			}
			else {
				UserPortList.SelectedPort = null;
			}
			
			//组件鼠标事件
			if( myModule != null && !ObjectPress ) {
				bool tttObjectPress = myModule.UserMouseDown( e, (int)MousePoint.X, (int)MousePoint.Y );
			}
			BackPress = !ObjectPress;
		}
		if( e.Button == MouseButtons.Right ) {
			
			RightMouseDown = true;
			
			if( UserPortList.MouseOnPort != null ) {
				//重定位网格偏移量
				//if( n_Main.Program.ModuleBox.checkBoxAutoLocat.Checked ) {
					UserPort.ox = UserPortList.MouseOnPort.X % UserPort.Per;
					UserPort.oy = UserPortList.MouseOnPort.Y % UserPort.Per;
				//}
				
				//2020.2.29 增加端口选中
				UserPortList.SelectedPort = UserPortList.MouseOnPort;
				//右键选中后鼠标移动时抖动会拖动网格, 可能导致误操作
				RightMouseDown = false;
			}
			
			lastX = e.X;
			lastY = e.Y;
		}
		this.Invalidate();
	}
	
	//鼠标松开事件
	void UserMouseUp( object sender, MouseEventArgs e )
	{
		if( e.Button == MouseButtons.Left ) {
			BackPress = false;
			
			//this.Cursor = Cursor1;
			
			//端口列表鼠标事件
			myPortList.UserMouseUp( e, (int)MousePoint.X, (int)MousePoint.Y );
			
			//组件鼠标事件
			if( myModule != null ) {
				myModule.UserMouseUp( e, (int)MousePoint.X, (int)MousePoint.Y );
			}
		}
		if( e.Button == MouseButtons.Right ) {
			RightMouseDown = false;
		}
		this.Invalidate();
	}
	
	//鼠标移动事件
	void UserMouseMove( object sender, MouseEventArgs e )
	{
		float ox = -(e.X - lastX) / CamScale;
		float oy = -(e.Y - lastY) / CamScale;
		double dx = ox;
		double dy = oy;
		
		if( RightMouseDown ) {
			UserPort.ox -= (float)dx;
			UserPort.oy -= (float)dy;
			UserPort.ox %= UserPort.Per;
			UserPort.oy %= UserPort.Per;
		}
		else {
			//端口列表鼠标事件
			myPortList.UserMouseMove( e, (int)MousePoint.X, (int)MousePoint.Y );
		}
		//组件鼠标事件
		if( myModule != null ) {
			myModule.UserMouseMove( e, (int)MousePoint.X, (int)MousePoint.Y );
		}
		MousePoint = GetWorldPoint( e.X, e.Y );
		if( BackPress && !n_Main.Program.ModuleBox.checkBoxAllMove.Checked ) {
			CamMidX += (float)dx;
			CamMidY += (float)dy;
		}
		//判断是否拖动全部端口
		if( e.Button == MouseButtons.Left && n_Main.Program.ModuleBox.checkBoxAllMove.Checked ) {
			
			//分发端口鼠标移动事件
			for( int i = 0; i < myPortList.PortList.Length; ++i ) {
				if( myPortList.PortList[i] == null ) {
					continue;
				}
				myPortList.PortList[i].X -= (float)dx;
				myPortList.PortList[i].Y -= (float)dy;
			}
		}
		
		lastX = e.X;
		lastY = e.Y;
		
		this.Invalidate();
	}
	
	//绘制网格点
	void DrawCrossPoint( Graphics g )
	{
		int WidthNumber = InitW / UserPort.Per;
		int HeightNumber = InitH / UserPort.Per;
		
		for( int i = 0; i <= WidthNumber; ++i ) {
			for( int j = 0; j <= HeightNumber; ++j ) {
				float x = UserPort.ox + i * UserPort.Per;
				float y = UserPort.oy + j * UserPort.Per;
				g.FillRectangle( Brushes.OrangeRed, x - 0.25f, y - 0.25f, 0.5f, 0.5f );
			}
		}
	}
	
	//绘制网格线
	void DrawCrossLine( Graphics g )
	{
		int WidthNumber = InitW / UserPort.Per;
		int HeightNumber = InitH / UserPort.Per;
		
		for( int i = 0; i <= WidthNumber; ++i ) {
			float x = UserPort.ox + i * UserPort.Per;
			if( i % 10 == 0 ) {
				g.DrawLine( GridPen10, x, 0, x, HeightNumber*UserPort.Per );
			}
			else {
				g.DrawLine( GridPen, x, 0, x, HeightNumber*UserPort.Per );
			}
		}
		for( int i = 0; i <= HeightNumber; ++i ) {
			float y = UserPort.oy + i * UserPort.Per;
			if( i % 10 == 0 ) {
				g.DrawLine( GridPen10, 0, y, WidthNumber*UserPort.Per, y );
			}
			else {
				g.DrawLine( GridPen, 0, y, WidthNumber*UserPort.Per, y );
			}
		}
	}
}
}


